home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ohlcpio.zip / COPYIN.C < prev    next >
C/C++ Source or Header  |  1990-07-07  |  16KB  |  580 lines

  1. /* copyin.c - cpio copy in sub-function.
  2.    Copyright (C) 1988, 1989, 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #ifndef S_IFLNK
  22. #define lstat stat
  23. #endif
  24. #include <errno.h>
  25. extern int errno;
  26. #include <fcntl.h>
  27. #include <sys/file.h>
  28. #ifdef USG
  29. #include <time.h>
  30. #include <string.h>
  31. #include <sys/sysmacros.h>
  32. #else
  33. #include <sys/time.h>
  34. #include <strings.h>
  35. #endif
  36. #include "cpio.h"
  37. #include "dstring.h"
  38. #include "extern.h"
  39.  
  40. void bcopy ();
  41.  
  42. void read_in_ascii ();
  43. void read_in_binary ();
  44. void mode_string ();
  45. void print_name_with_quoting ();
  46. void swab_array ();
  47.  
  48. /* Return 16-bit integer I with the bytes swapped. */
  49. #define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
  50.  
  51. /* Read header, including the name of the file, from file
  52.    descriptor IN_DES into FILE_HDR.  */
  53.  
  54. void
  55. read_in_header (file_hdr, in_des)
  56.      struct cpio_header *file_hdr;
  57.      int in_des;
  58. {
  59.   long bytes_skipped = 0;    /* Bytes of junk found before magic number. */
  60.  
  61.   /* Search for valid magic number. */
  62.   copy_in_buf ((char *) file_hdr, in_des, 6);
  63.   while (1)
  64.   {
  65.     if (portability_flag && !strncmp ((char *) file_hdr, "070707", 6))
  66.       {
  67.     if (bytes_skipped > 0)
  68.       error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
  69.     read_in_ascii (file_hdr, in_des);
  70.     break;
  71.       }
  72.     if (binary_flag
  73.     && (file_hdr->h_magic == 070707
  74.         || file_hdr->h_magic == swab_short ((unsigned short) 070707)))
  75.       {
  76.     /* Having to skip 1 byte because of word alignment is normal. */
  77.     if (bytes_skipped > 1)
  78.       error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
  79.     read_in_binary (file_hdr, in_des);
  80.     break;
  81.       }
  82.     bytes_skipped++;
  83.     bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
  84.     copy_in_buf ((char *) file_hdr + 5, in_des, 1);
  85.   }
  86. }
  87.  
  88. /* Fill in FILE_HDR by reading an ASCII format cpio header from
  89.    file descriptor IN_DES, except for the magic number, which is
  90.    already filled in. */
  91.  
  92. void
  93. read_in_ascii (file_hdr, in_des)
  94.      struct cpio_header *file_hdr;
  95.      int in_des;
  96. {
  97.   char ascii_header[78];
  98.  
  99.   copy_in_buf (ascii_header, in_des, 70);
  100.   ascii_header[70] = '\0';
  101.   sscanf (ascii_header,
  102.       "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
  103.       &file_hdr->h_dev, &file_hdr->h_ino,
  104.       &file_hdr->h_mode, &file_hdr->h_uid, &file_hdr->h_gid,
  105.       &file_hdr->h_nlink, &file_hdr->h_rdev, &file_hdr->h_mtime,
  106.       &file_hdr->h_namesize, &file_hdr->h_filesize);
  107.  
  108.   /* Read file name from input.  */
  109.   if (file_hdr->h_name != NULL)
  110.     free (file_hdr->h_name);
  111.   file_hdr->h_name = (char *) xmalloc (file_hdr->h_namesize);
  112.   copy_in_buf (file_hdr->h_name, in_des, file_hdr->h_namesize);
  113. }
  114.  
  115. /* Fill in FILE_HDR by reading a binary format cpio header from
  116.    file descriptor IN_DES, except for the first 6 bytes, which are
  117.    already filled in. */
  118.  
  119. void
  120. read_in_binary (file_hdr, in_des)
  121.      struct cpio_header *file_hdr;
  122.      int in_des;
  123. {
  124.   copy_in_buf ((char *) file_hdr + 6, in_des, 20);
  125.  
  126.   /* If correct magic number but byte swapped, fix the header. */
  127.   if (file_hdr->h_magic == swab_short ((unsigned short) 070707))
  128.     {
  129.       static int warned = 0;
  130.       
  131.       /* Alert the user that they might have to do byte swapping on
  132.      the file contents. */
  133.       if (warned == 0)
  134.     {
  135.       error (0, 0, "warning: archive header has reverse byte-order");
  136.       warned = 1;
  137.     }
  138.       swab_array ((short *) file_hdr, 13);
  139.     }
  140.  
  141.   file_hdr->h_mtime = file_hdr->h_mtimes[0] << 16 | file_hdr->h_mtimes[1];
  142.  
  143.   file_hdr->h_filesize = file_hdr->h_filesizes[0] << 16
  144.     | file_hdr->h_filesizes[1];
  145.  
  146.   /* Read file name from input.  */
  147.   if (file_hdr->h_name != NULL)
  148.     free (file_hdr->h_name);
  149.   file_hdr->h_name = (char *) xmalloc (file_hdr->h_namesize);
  150.   copy_in_buf (file_hdr->h_name, in_des, file_hdr->h_namesize);
  151.  
  152.   /* In binary mode, the amount of space allocated in the header for
  153.      the filename is `h_namesize' rounded up to the next short-word,
  154.      so we might need to drop a byte. */
  155.   if (file_hdr->h_namesize % 2)
  156.     toss_input (in_des, 1);
  157. }
  158.  
  159. /* Exchange the bytes of each element of the array of COUNT shorts
  160.    starting at PTR. */
  161.  
  162. void
  163. swab_array (ptr, count)
  164.      short *ptr;
  165.      int count;
  166. {
  167.   while (count-- > 0)
  168.     {
  169.       *ptr = swab_short (*ptr);
  170.       ++ptr;
  171.     }
  172. }
  173.  
  174. /* Current time for verbose table. */
  175. static long current_time;
  176.  
  177. /* Read the collection from standard input and create files
  178.    in the file system.  */
  179.  
  180. void
  181. process_copy_in ()
  182. {
  183.   char done = FALSE;        /* True if trailer reached.  */
  184.   int res;            /* Result of various function calls.  */
  185.   dynamic_string new_name;    /* New file name for rename option.  */
  186.   FILE *tty_in;            /* Interactive file for rename option.  */
  187.   FILE *tty_out;        /* Interactive file for rename option.  */
  188.   char *str_res;        /* Result for string function.  */
  189.   long times[2];        /* For setting file times.  */
  190.   struct stat file_stat;    /* Output file stat record.  */
  191.   struct cpio_header file_hdr;    /* Output header information.  */
  192.   int out_file_des;        /* Output file descriptor.  */
  193.   int in_file_des;        /* Input file descriptor.  */
  194.   char skip_file;        /* Flag for use with patterns.  */
  195.   int i;            /* Loop index variable.  */
  196.   char *link_name = NULL;    /* Name of hard and symbolic links.  */
  197.  
  198.   /* Initialize copy in.  */
  199.   file_hdr.h_name = NULL;
  200.   ds_init (&new_name, 128);
  201.  
  202.   /* Open interactive file pair for rename operation.  */
  203.   if (rename_flag)
  204.     {
  205.       tty_in = fopen ("/dev/tty", "r");
  206.       if (tty_in == NULL)
  207.     error (2, errno, "/dev/tty");
  208.       tty_out = fopen ("/dev/tty", "w");
  209.       if (tty_out == NULL)
  210.     error (2, errno, "/dev/tty");
  211.     }
  212.  
  213.   /* Get date and time if needed for processing the table option. */
  214.   if (table_flag && verbose_flag)
  215.     time (¤t_time);
  216.  
  217.   /* Check whether the input file might be a tape.  */
  218.   in_file_des = fileno (stdin);
  219.   if (fstat (in_file_des, &file_stat))
  220.     error (1, errno, "standard input is closed");
  221.   input_is_special = ((file_stat.st_mode & S_IFMT) == S_IFCHR
  222.               || (file_stat.st_mode & S_IFMT) == S_IFBLK);
  223.   input_is_seekable = ((file_stat.st_mode & S_IFMT) == S_IFREG);
  224.   output_is_seekable = TRUE;
  225.  
  226.   /* While there is more input in collection, process the input.  */
  227.   while (!done)
  228.     {
  229.       /* Start processing the next file by reading the header. */
  230.       read_in_header (&file_hdr, in_file_des);
  231.  
  232.       /* Is this the header for the TRAILER file?  */
  233.       if (strcmp ("TRAILER!!!", file_hdr.h_name) == 0)
  234.     {
  235.       done = TRUE;
  236.       break;
  237.     }
  238.  
  239.       /* Does the file name match one of the given patterns?  */
  240.       if (num_patterns <= 0)
  241.     skip_file = FALSE;
  242.       else
  243.     {
  244.       skip_file = copy_matching_files;
  245.       for (i = 0; i < num_patterns
  246.            && skip_file == copy_matching_files; i++)
  247.         {
  248.           if (glob_match (save_patterns[i], file_hdr.h_name, 0) == 1)
  249.         skip_file = !copy_matching_files;
  250.         }
  251.     }
  252.  
  253.       if (skip_file)
  254.     toss_input (in_file_des, file_hdr.h_filesize);
  255.       else if (table_flag)
  256.     {
  257.       if (verbose_flag)
  258.         {
  259. #ifdef S_IFLNK
  260.           if ((file_hdr.h_mode & S_IFMT) == S_IFLNK)
  261.         {
  262.           link_name = (char *) xmalloc (file_hdr.h_filesize + 1);
  263.           link_name[file_hdr.h_filesize] = '\0';
  264.           copy_in_buf (link_name, in_file_des, file_hdr.h_filesize);
  265.           long_format (&file_hdr, link_name);
  266.           free (link_name);
  267.           file_hdr.h_filesize = 0;
  268.         }
  269.           else
  270. #endif
  271.         long_format (&file_hdr, (char *) 0);
  272.         }
  273.       else
  274.         printf ("%s\n", file_hdr.h_name);
  275.       toss_input (in_file_des, file_hdr.h_filesize);
  276.     }
  277.       else
  278.     {
  279.       /* Copy the input file into the directory structure.  */
  280.  
  281.       /* Do we need to rename the file? */
  282.       if (rename_flag)
  283.         {
  284.           fprintf (tty_out, "rename %s -> ", file_hdr.h_name);
  285.           fflush (tty_out);
  286.           str_res = ds_fgets (tty_in, &new_name);
  287.           if (str_res == NULL || str_res[0] == 0)
  288.         {
  289.           toss_input (in_file_des, file_hdr.h_filesize);
  290.           continue;
  291.         }
  292.           else
  293.         file_hdr.h_name = copystring (new_name.ds_string);
  294.         }
  295.  
  296.       /* See if the file already exists. */
  297.       if (lstat (file_hdr.h_name, &file_stat) == 0)
  298.         {
  299.           if (!unconditional_flag
  300.           && file_hdr.h_mtime < file_stat.st_mtime)
  301.         {
  302.           error (0, 0, "%s not created: newer version exists",
  303.              file_hdr.h_name);
  304.           toss_input (in_file_des, file_hdr.h_filesize);
  305.           continue;    /* Go to the next file. */
  306.         }
  307.           else if ((file_stat.st_mode & S_IFMT) == S_IFDIR)
  308.         {
  309.           error (0, 0, "cannot remove current %s: Is a directory",
  310.              file_hdr.h_name);
  311.           toss_input (in_file_des, file_hdr.h_filesize);
  312.           continue;    /* Go to the next file. */
  313.         }
  314.           else if (unlink (file_hdr.h_name))
  315.         {
  316.           error (0, errno, "cannot remove current %s",
  317.              file_hdr.h_name);
  318.           toss_input (in_file_des, file_hdr.h_filesize);
  319.           continue;    /* Go to the next file. */
  320.         }          
  321.         }
  322.  
  323.       /* Do the real copy or link.  */
  324.       switch (file_hdr.h_mode & S_IFMT)
  325.         {
  326.         case S_IFREG:
  327.           /* Can the current file be linked to a previously copied file? */
  328.           if (file_hdr.h_nlink > 1)
  329.         {
  330.           link_name = find_inode_file (file_hdr.h_ino);
  331.           if (link_name == NULL)
  332.             add_inode (file_hdr.h_ino, file_hdr.h_name);
  333.           else
  334.             {
  335.               res = link (link_name, file_hdr.h_name);
  336.               if (res < 0 && create_dir_flag)
  337.             {
  338.               create_all_directories (file_hdr.h_name);
  339.               res = link (link_name, file_hdr.h_name);
  340.             }
  341.               if (res == 0)
  342.             {
  343.               if (verbose_flag)
  344.                 error (0, 0, "%s linked to %s",
  345.                    link_name, file_hdr.h_name);
  346.               toss_input (in_file_des, file_hdr.h_filesize);
  347.             }
  348.               else
  349.             link_name = NULL;
  350.             }
  351.         }
  352.  
  353.           /* If not linked, copy the contents of the file. */
  354.           if (link_name == NULL)
  355.         {
  356.           out_file_des = open (file_hdr.h_name,
  357.                        O_CREAT | O_WRONLY, 0600);
  358.           if (out_file_des < 0 && create_dir_flag)
  359.             {
  360.               create_all_directories (file_hdr.h_name);
  361.               out_file_des = open (file_hdr.h_name,
  362.                        O_CREAT | O_WRONLY, 0600);
  363.             }
  364.           if (out_file_des < 0)
  365.             {
  366.               error (0, errno, "%s", file_hdr.h_name);
  367.               toss_input (in_file_des, file_hdr.h_filesize);
  368.               continue;
  369.             }
  370.  
  371.           copy_files (in_file_des, out_file_des, file_hdr.h_filesize);
  372.           empty_output_buffer (out_file_des);
  373.           finish_output_file (file_hdr.h_name, out_file_des);
  374.           close (out_file_des);
  375.  
  376.           /* File is now copied; set attributes.  */
  377.           if (chmod (file_hdr.h_name, file_hdr.h_mode) < 0)
  378.             error (0, errno, "%s", file_hdr.h_name);
  379.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  380.                  file_hdr.h_gid) < 0
  381.               && errno != EPERM)
  382.             error (0, errno, "%s", file_hdr.h_name);
  383.           if (retain_time_flag)
  384.             {
  385.               times[0] = times[1] = file_hdr.h_mtime;
  386.               if (utime (file_hdr.h_name, times) < 0)
  387.             error (0, errno, "%s", file_hdr.h_name);
  388.             }
  389.         }
  390.           break;
  391.  
  392.         case S_IFDIR:
  393.           res = mkdir (file_hdr.h_name, file_hdr.h_mode);
  394.           if (res < 0 && create_dir_flag)
  395.         {
  396.           create_all_directories (file_hdr.h_name);
  397.           res = mkdir (file_hdr.h_name, file_hdr.h_mode);
  398.         }
  399.           if (res < 0)
  400.         {
  401.           error (0, errno, "%s", file_hdr.h_name);
  402.           continue;
  403.         }
  404.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  405.              file_hdr.h_gid) < 0
  406.           && errno != EPERM)
  407.         error (0, errno, "%s", file_hdr.h_name);
  408.           break;
  409.  
  410.         case S_IFCHR:
  411.         case S_IFBLK:
  412. #ifdef S_IFSOCK
  413.         case S_IFSOCK:
  414. #endif
  415. #ifdef S_IFIFO
  416.         case S_IFIFO:
  417. #endif
  418.           res = mknod (file_hdr.h_name, file_hdr.h_mode, file_hdr.h_rdev);
  419.           if (res < 0 && create_dir_flag)
  420.         {
  421.           create_all_directories (file_hdr.h_name);
  422.           res = mknod (file_hdr.h_name, file_hdr.h_mode,
  423.                    file_hdr.h_rdev);
  424.         }
  425.           if (res < 0)
  426.         {
  427.           error (0, errno, "%s", file_hdr.h_name);
  428.           continue;
  429.         }
  430.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  431.              file_hdr.h_gid) < 0
  432.           && errno != EPERM)
  433.         error (0, errno, "%s", file_hdr.h_name);
  434.           break;
  435.  
  436. #ifdef S_IFLNK
  437.         case S_IFLNK:
  438.           {
  439.         link_name = (char *) xmalloc (file_hdr.h_filesize + 1);
  440.         link_name[file_hdr.h_filesize] = '\0';
  441.         copy_in_buf (link_name, in_file_des, file_hdr.h_filesize);
  442.  
  443.         res = symlink (link_name, file_hdr.h_name);
  444.         if (res < 0 && create_dir_flag)
  445.           {
  446.             create_all_directories (file_hdr.h_name);
  447.             res = symlink (link_name, file_hdr.h_name);
  448.           }
  449.         if (res < 0)
  450.           {
  451.             error (0, errno, "%s", file_hdr.h_name);
  452.             free (link_name);
  453.             continue;
  454.           }
  455.         free (link_name);
  456.           }
  457.           break;
  458. #endif
  459.  
  460.         default:
  461.           error (0, 0, "%s: unknown file type", file_hdr.h_name);
  462.           toss_input (in_file_des, file_hdr.h_filesize);
  463.         }
  464.  
  465.       if (verbose_flag)
  466.         fprintf (stderr, "%s\n", file_hdr.h_name);
  467.     }
  468.     }
  469.   res = (input_bytes + io_block_size - 1) / io_block_size;
  470.   if (res == 1)
  471.     fprintf (stderr, "1 block\n");
  472.   else
  473.     fprintf (stderr, "%d blocks\n", res);
  474. }
  475.  
  476. /* Print the file described by FILE_HDR in long format.
  477.    If LINK_NAME is nonzero, it is the name of the file that
  478.    this file is a symbolic link to.  */
  479.  
  480. void
  481. long_format (file_hdr, link_name)
  482.      struct cpio_header *file_hdr;
  483.      char *link_name;
  484. {
  485.   char mbuf[11];
  486.   char tbuf[40];
  487.   long when;
  488.  
  489.   mode_string (file_hdr->h_mode, mbuf);
  490.   mbuf[10] = '\0';
  491.  
  492.   /* Get time values ready to print. */
  493.   when = file_hdr->h_mtime;
  494.   strcpy (tbuf, ctime (&when));
  495.   if (current_time - when > 6L * 30L * 24L * 60L * 60L
  496.       || current_time - when < 0L)
  497.     {
  498.       /* The file is older than 6 months, or in the future.
  499.      Show the year instead of the time of day.  */
  500.       strcpy (tbuf + 11, tbuf + 19);
  501.     }
  502.   tbuf[16] = '\0';
  503.  
  504.   printf ("%s %3u ", mbuf, file_hdr->h_nlink);
  505.  
  506.   if (numeric_uid)
  507.     printf ("%-8u %-8u ", file_hdr->h_uid, file_hdr->h_gid);
  508.   else
  509.     printf ("%-8.8s %-8.8s ", getuser (file_hdr->h_uid),
  510.         getgroup (file_hdr->h_gid));
  511.  
  512.   if ((file_hdr->h_mode & S_IFMT) == S_IFCHR
  513.       || (file_hdr->h_mode & S_IFMT) == S_IFBLK)
  514.     printf ("%3u, %3u ", major (file_hdr->h_rdev),
  515.         minor (file_hdr->h_rdev));
  516.   else
  517.     printf ("%8u ", file_hdr->h_filesize);
  518.  
  519.   printf ("%s ", tbuf + 4);
  520.  
  521.   print_name_with_quoting (file_hdr->h_name);
  522.   if (link_name)
  523.     {
  524.       printf (" -> ");
  525.       print_name_with_quoting (link_name);
  526.     }
  527.   putc ('\n', stdout);
  528. }
  529.  
  530. void
  531. print_name_with_quoting (p)
  532.      register char *p;
  533. {
  534.   register unsigned char c;
  535.  
  536.   while (c = *p++)
  537.     {
  538.       switch (c)
  539.     {
  540.     case '\\':
  541.       printf ("\\\\");
  542.       break;
  543.  
  544.     case '\n':
  545.       printf ("\\n");
  546.       break;
  547.  
  548.     case '\b':
  549.       printf ("\\b");
  550.       break;
  551.  
  552.     case '\r':
  553.       printf ("\\r");
  554.       break;
  555.  
  556.     case '\t':
  557.       printf ("\\t");
  558.       break;
  559.  
  560.     case '\f':
  561.       printf ("\\f");
  562.       break;
  563.  
  564.     case ' ':
  565.       printf ("\\ ");
  566.       break;
  567.  
  568.     case '"':
  569.       printf ("\\\"");
  570.       break;
  571.  
  572.     default:
  573.       if (c > 040 && c < 0177)
  574.         putchar (c);
  575.       else
  576.         printf ("\\%03o", (unsigned int) c);
  577.     }
  578.     }
  579. }
  580.